The `optimize' and `extensions:optimize-interface' declarations (?) set
up the global compilation policy. The bodies of functions are to be
compiled completely unsafe (`safety 0'), but argument count and weakened
argument type checking is to be done when a function is called (`speed 2
safety 1').
The first declaration specifies that all functions that are external or
whose names contain both "`%'" and "`SET'" are to be compiled compiled
with completely safe interfaces (`safety 2'). The reason for this
particular :match rule is that `setf' inverse functions in this system
tend to have both strings in their name somewhere. We want `setf'
inverses to be safe because they are implicitly called by users even
though their name is not exported.
The second declaration makes external macros or functions whose names
start with "`PARSE-'" have safe bodies (as well as interfaces). This is
desirable because a syntax error in a macro may cause a type error
inside the body. The :match rule is used because macros often have
auxiliary functions whose names begin with this string.
This particular example is used to build part of the standard CMU Common
Lisp system. Note however, that context declarations must be set up
according to the needs and coding conventions of a particular system;
different parts of CMU Common Lisp are compiled with different context
declarations, and your system will probably need its own declarations.
In particular, any use of the :match option depends on naming
conventions used in coding.
File: cmu-user.info Node: Interpreting Error Messages, Prev: Compilation Units, Up: The Compiler, Next: Types in Python
Interpreting Error Messages
===========================
One of Python's unique features is the level of source location information it
provides in error messages. The error messages contain a lot of detail in a
terse format, to they may be confusing at first. Error messages will be
illustrated using this example program:
(defmacro zoq (x)
`(roq (ploq (+ ,x 3))))
(defun foo (y)
(declare (symbol y))
(zoq y))
The main problem with this program is that it is trying to add `3' to a
symbol. Note also that the functions `roq' and `ploq' aren't defined
anywhere.
* Menu:
* The Parts of the Error Message::
* The Original and Actual Source::
* The Processing Path::
* Error Severity::
* Errors During Macroexpansion::
* Read Errors::
* Error Message Parameterization::
File: cmu-user.info Node: The Parts of the Error Message, Prev: Interpreting Error Messages, Up: Interpreting Error Messages, Next: The Original and Actual Source
The Parts of the Error Message
------------------------------
The compiler will produce this warning:
File: /usr/me/stuff.lisp
In: DEFUN FOO
(ZOQ Y)
--> ROQ PLOQ +
==>
Y Warning: Result is a SYMBOL, not a NUMBER.
In this example we see each of the six possible parts of a compiler error
message:
`File: /usr/me/stuff.lisp'
This is the FILE that the compiler read the relevant code from.
The file name is displayed because it may not be immediately
obvious when there is an error during compilation of a large
system, especially when `with-compilation-unit' is used to delay
undefined warnings.
`In: DEFUN FOO'
This is the DEFINITION or top-level form responsible for the error.
It is obtained by taking the first two elements of the enclosing
form whose first element is a symbol beginning with "`DEF'". If
there is no enclosing DEFmumble, then the outermost form is used.
If there are multiple DEFmumbles, then they are all printed from
the out in, separated by `=>''s. In this example, the problem was
in the `defun' for `foo'.
`(ZOQ Y)'
This is the original source form responsible for the error.
Original source means that the form directly appeared in the
original input to the compiler, i.e. in the lambda passed to
`compile' or the top-level form read from the source file. In this
example, the expansion of the `zoq' macro was responsible for the
error.
`--> ROQ PLOQ +'
This is the processing path that the compiler used to produce the
errorful code. The processing path is a representation of the
evaluated forms enclosing the actual source that the compiler
encountered when processing the original source. The path is the
first element of each form, or the form itself if the form is not a
list. These forms result from the expansion of macros or
source-to-source transformation done by the compiler. In this
example, the enclosing evaluated forms are the calls to `roq',
`ploq' and `+'. These calls resulted from the expansion of the
`zoq' macro.
`==> Y'
This is the actual source responsible for the error. If the actual
source appears in the explanation, then we print the next enclosing
evaluated form, instead of printing the actual source twice. (This
is the form that would otherwise have been the last form of the
processing path.) In this example, the problem is with the
evaluation of the reference to the variable `y'.
`Warning: Result is a SYMBOL, not a NUMBER.'
This is the EXPLANATION the problem. In this example, the problem
is that `y' evaluates to a `symbol', but is in a context where a
number is required (the argument to `+').
Note that each part of the error message is distinctively marked:
* `File:' and `In:' mark the file and definition, respectively.
* The original source is an indented form with no prefix.
* Each line of the processing path is prefixed with `-->'.
* The actual source form is indented like the original source, but is
marked by a preceding `==>' line. This is like the "macroexpands
to" notation used in i{Common Lisp: The Language}.
* The explanation is prefixed with the error severity (?), either
`Error:', `Warning:', or `Note:'.
Each part of the error message is more specific than the preceding one. If
consecutive error messages are for nearby locations, then the front part of the
error messages would be the same. In this case, the compiler omits as much of
the second message as in common with the first. For example:
File: /usr/me/stuff.lisp
In: DEFUN FOO
(ZOQ Y)
--> ROQ
==>
(PLOQ (+ Y 3))
Warning: Undefined function: PLOQ
==>
(ROQ (PLOQ (+ Y 3)))
Warning: Undefined function: ROQ
In this example, the file, definition and original source are identical for the
two messages, so the compiler omits them in the second message. If consecutive
messages are entirely identical, then the compiler prints only the first
message, followed by:
[Last message occurs REPEATS times]
where REPEATS is the number of times the message was given.
If the source was not from a file, then no file line is printed. If the
actual source is the same as the original source, then the processing
path and actual source will be omitted. If no forms intervene between
the original source and the actual source, then the processing path will
also be omitted.
File: cmu-user.info Node: The Original and Actual Source, Prev: The Parts of the Error Message, Up: Interpreting Error Messages, Next: The Processing Path
The Original and Actual Source
------------------------------
The original source displayed will almost always be a list. If the actual
source for an error message is a symbol, the original source will be the
immediately enclosing evaluated list form. So even if the offending symbol
does appear in the original source, the compiler will print the enclosing list
and then print the symbol as the actual source (as though the symbol were
introduced by a macro.)
When the actual source is displayed (and is not a symbol), it will
always be code that resulted from the expansion of a macro or a
source-to-source compiler optimization. This is code that did not
appear in the original source program; it was introduced by the
compiler.
Keep in mind that when the compiler displays a source form in an error message,
it always displays the most specific (innermost) responsible form. For
example, compiling this function:
(defun bar (x)
(let (a)
(declare (fixnum a))
(setq a (foo x))
a))
Gives this error message:
In: DEFUN BAR
(LET (A) (DECLARE (FIXNUM A)) (SETQ A (FOO X)) A)
Warning: The binding of A is not a FIXNUM:
NIL
This error message is not saying "there's a problem somewhere in this
`let'" -- it is saying that there is a problem with the `let' itself.
In this example, the problem is that `a''s false initial value is not a
`fixnum'.
File: cmu-user.info Node: The Processing Path, Prev: The Original and Actual Source, Up: Interpreting Error Messages, Next: Error Severity
The Processing Path
-------------------
The processing path is mainly useful for debugging macros, so if you don't
write macros, you can ignore the processing path. Consider this example:
(defun foo (n)
(dotimes (i n *undefined*)))
Compiling results in this error message:
In: DEFUN FOO
(DOTIMES (I N *UNDEFINED*))
--> DO BLOCK LET TAGBODY RETURN-FROM
==>
(PROGN *UNDEFINED*)
Warning: Undefined variable: *UNDEFINED*
Note that `do' appears in the processing path. This is because `dotimes'
expands into:
(do ((i 0 (1+ i)) (#:g1 n))
((>= i #:g1) *undefined*)
(declare (type unsigned-byte i)))
The rest of the processing path results from the expansion of `do':
(block nil
(let ((i 0) (#:g1 n))
(declare (type unsigned-byte i))
(tagbody (go #:g3)
#:g2 (psetq i (1+ i))
#:g3 (unless (>= i #:g1) (go #:g2))
(return-from nil (progn *undefined*)))))
In this example, the compiler descended into the `block', `let',
`tagbody' and `return-from' to reach the `progn' printed as the actual
source. This is a place where the "actual source appears in
explanation" rule was applied. The innermost actual source form was the
symbol `*undefined*' itself, but that also appeared in the explanation,
so the compiler backed out one level.
File: cmu-user.info Node: Error Severity, Prev: The Processing Path, Up: Interpreting Error Messages, Next: Errors During Macroexpansion
Error Severity
--------------
There are three levels of compiler error severity:
Error
This severity is used when the compiler encounters a problem
serious enough to prevent normal processing of a form. Instead of
compiling the form, the compiler compiles a call to `error'.
Errors are used mainly for signalling syntax errors. If an error
happens during macroexpansion, the compiler will handle it. The
compiler also handles and attempts to proceed from read errors.
Warning
Warnings are used when the compiler can prove that something bad will happen
if a portion of the program is executed, but the compiler can proceed by
compiling code that signals an error at runtime if the problem has not been
fixed:
* Violation of type declarations, or
* Function calls that have the wrong number of arguments or malformed keyword
argument lists, or
* Referencing a variable declared `ignore', or unrecognized
declaration specifiers.
In the language of the CMU Common Lisp standard, these are
situations where the compiler can determine that a situation with
undefined consequences or that would cause an error to be signalled
would result at runtime.
Note
Notes are used when there is something that seems a bit odd, but
that might reasonably appear in correct programs.
Note that the compiler does not fully conform to the proposed X3J13
"compiler-diagnostics" cleanup. Errors, warnings and notes mostly
correspond to errors, warnings and style-warnings, but many things that
the cleanup considers to be style-warnings are printed as warnings
rather than notes. Also, warnings, style-warnings and most errors
aren't really signalled using the condition system.